package org.orbis.status;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.SortedSet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.orbis.communicate.Configuration;
import org.orbis.communicate.MainService;
import org.orbis.communicate.node.Node;
import org.orbis.constants.Constants;
import org.orbis.index.IndexingPackage;
import org.orbis.memorycontroller.struct.MemoryInfoMaterial;
import org.orbis.structure.ContentInfo;
import org.orbis.tool.Header;

public class ShowStatus extends HttpServlet{
	private static final long serialVersionUID = -5896201191130988921L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
		IOException{
		resp.setCharacterEncoding("UTF-8");
		
		MainService srv = MainService.getInstance();
		ArrayList<MemoryInfoMaterial> meminfo = srv.getStatusList();
		Configuration conf = srv.getConf();
		ContentInfo contentInfo = conf.contentInfo();
		PrintWriter out = resp.getWriter();

		out.println("<!DOCTYPE html>");
		out.println("<html>");
		out.println("<head>");
		out.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
		out.println("<title>ORBIS Search System: Status</title>");
		out.println("</head>");
		out.println("<body>");

		// Title bar
		out.println(Header.getTitleBar("ORBIS Search System: Status"));

		// Header
		out.println(Header.getHeader(0));
		
		out.println("<div style=\"background:#268eab; color:#ffffff;\">");
		out.println("<h3> Global environment </h3>");
		out.println("</div>");

		out.println("<table style=\"margin: 15px;\">");
		out.println("<tbody>");

		out.println("<tr>");
		out.println("<td style=\"text-align: right;\">Data directory:</td>");
		out.println("<td style=\"text-align: right;\">");
		out.println(conf.workDirectory());
		out.println("</td>");
		out.println("</tr>");

		out.println("<tr>");
		out.println("<td style=\"text-align: right;\">Log directory:</td>");
		out.println("<td style=\"text-align: right;\">");
		out.println(conf.logDirectory());
		out.println("</td>");
		out.println("</tr>");

		out.println("<tr>");
		out.println("<td style=\"text-align: right;\">Startup:</td>");
		out.println("<td style=\"text-align: right;\">");
		out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(srv.startSec())));
		out.println("</td>");
		out.println("</tr>");

		out.println("<tr>");
		out.println("<td style=\"text-align: right;\">Uptime:</td>");
		out.println("<td align=\"right\">");
		long timesec = (System.currentTimeMillis() - srv.startSec()) / 1000;
		if(timesec >= 86400) out.println((timesec / 86400) + " day ");
		if(timesec >= 3600) out.println(((timesec / 3600) % 24) + " hr. ");
		if(timesec >= 60) out.println(((timesec / 60) % 60) + " min. ");
		out.println((timesec % 60) + " sec.");
		out.println("</td>");
		out.println("</tr>");

		out.println("<tr>");
		out.println("<td style=\"text-align: right;\">Beacon interval:</td>");
		out.println("<td align=\"right\">");
		out.println(conf.beaconInterval() + " sec.");
		out.println("</td>");
		out.println("</tr>");

		out.println("<tr>");
		out.println("<td style=\"text-align: right;\">Beacon deadline:</td>");
		out.println("<td align=\"right\">");
		out.println("No response by " + conf.beaconThreshold() + " times");
		out.println("</td>");
		out.println("</tr>");

		out.println("<tr>");
		out.println("<td style=\"text-align: right;\">Backup interval:</td>");
		out.println("<td align=\"right\">");
		out.println(conf.backupInterval() + " min.");
		out.println("</td>");
		out.println("</tr>");

		out.println("<tr>");
		out.println("<td style=\"text-align: right;\">Index count:</td>");
		out.println("<td align=\"right\">");
		out.println(srv.getIndexCounter());
		out.println("</td>");
		out.println("</tr>");

		// out.println("<tr>");
		// out.println("<td>Index average response:</td>");
		// out.println("<td align=\"right\">");
		// out.println("[Stub]");
		// out.println("</td>");
		// out.println("</tr>");

		out.println("<tr>");
		out.println("<td style=\"text-align: right;\">Search count:</td>");
		out.println("<td align=\"right\">");
		out.println(srv.getSearchCounter());
		out.println("</td>");
		out.println("</tr>");

		// out.println("<tr>");
		// out.println("<td>Search average response:</td>");
		// out.println("<td align=\"right\">");
		// out.println("[Stub]");
		// out.println("</td>");
		// out.println("</tr>");

		out.println("<tr>");
		out.println("<td style=\"text-align: right;\">Delete count:</td>");
		out.println("<td align=\"right\">");
		out.println(srv.getDeleteCounter());
		out.println("</td>");
		out.println("</tr>");

		// out.println("<tr>");
		// out.println("<td>Delete average response:</td>");
		// out.println("<td align=\"right\">");
		// out.println("[Stub]");
		// out.println("</td>");
		// out.println("</tr>");

		out.println("<tr>");
		out.println("<td style=\"text-align: right;\">Term count:</td>");
		out.println("<td align=\"right\">");
		out.println(srv.getTerms());
		out.println("</td>");
		out.println("</tr>");

		out.println("<tr>");
		out.println("<td style=\"text-align: right;\">Query parser:</td>");
		out.println("<td align=\"right\">");
		out.println(srv.getConf().chopper().getClass().getName());
		out.println("</td>");
		out.println("</tr>");

		out.println("</tbody>");
		out.println("</table>");

		// ///////////////////////////////

		out.println("<div style=\"background:#268eab; color:#ffffff;\">");
		out.println("<h3> Index types </h3>");
		out.println("</div>");

		IndexingPackage pkg = srv.lastIndex();
		out.println("<div style=\"margin:15px; color:#ffffff; background:#1d6d82;\">");
		out.println("<h4> Content </h4>");
		out.println("</div>");

		out.println("<table style=\"margin: 25px;\">");
		out.println("<tbody>");
		out.println("<tr style=\"color: #ffffff; background: #155161;\">");
		out.println("<th>");
		out.println("Delete key");
		out.println("</th>");
		out.println("<th>");
		out.println("Field name");
		out.println("</th>");
		if(pkg != null){
			out.println("<th>");
			out.println("Latest indexed value");
			out.println("</th>");
		}
		out.println("</tr>");
		for(int i = 0; i < contentInfo.contentsNum(); i++){
			out.println("<tr style=\"background: " + (i % 2 == 0? "#cccccc": "#ffffff") + "\">");
			out.println("<td style=\"text-align: center;\"><b>");
			if(conf.contentDeleteType() == i)
				out.println("★");
			out.println("</b></td>");
			out.println("<td><b>");
			out.println(contentInfo.contentName(i));
			out.println("</b></td>");
			if(pkg != null){
				// DEBUG: Character code
				out.println("<td>");
				out.println(pkg.content(i));
				out.println("</td>");
			}
			out.println("</tr>");
		}
		out.println("</tbody>");
		out.println("</table>");

		if(contentInfo.appendixNum() != 0){
			out.println("<div style=\"margin: 15px; color:#ffffff; background:#1d6d82;\">");
			out.println("<h4> Appendix Field </h4>");
			out.println("</div>");

			out.println("<table style=\"margin: 25px;\">");
			out.println("<tbody>");
			out.println("<tr style=\"color: #ffffff; background: #155161;\">");
			out.println("<th>");
			out.println("Delete key");
			out.println("</th>");
			out.println("<th>");
			out.println("Field name");
			out.println("</th>");
			if(pkg != null){
				out.println("<th>");
				out.println("Latest indexed value");
				out.println("</th>");
			}
			out.println("</tr>");
			for(int i = 0; i < contentInfo.appendixNum(); i++){
				out.println("<tr style=\"background: " + (i % 2 == 0? "#cccccc": "#ffffff") + "\">");
				out.println("<td style=\"text-align: center;\"><b>");
				if(conf.appendixDeleteType() == i)
					out.println("★");
				out.println("</b></td>");
				out.println("<td><b>");
				out.println(contentInfo.appendixName(i));
				out.println("</b></td>");
				if(pkg != null){
					out.println("<td>");
					out.println(pkg.appendix(i));
					out.println("</td>");
				}
				out.println("</tr>");
			}
			out.println("</tbody>");
			out.println("</table>");
		}

		if(contentInfo.binaryFlagNum() != 0){
			out.println("<div style=\"margin: 15px; color:#ffffff; background:#1d6d82;\">");
			out.println("<h4> Binary Flag </h4>");
			out.println("</div>");

			out.println("<table style=\"margin: 25px;\">");
			out.println("<tbody>");
			out.println("<tr style=\"color: #ffffff; background: #155161;\">");
			out.println("<th>");
			out.println("Field name");
			out.println("</th>");
			if(pkg != null){
				out.println("<th>");
				out.println("Latest indexed value");
				out.println("</th>");
			}
			out.println("</tr>");
			for(int i = 0; i < contentInfo.binaryFlagNum(); i++){
				out.println("<tr style=\"background: " + (i % 2 == 0? "#cccccc": "#ffffff") + "\">");
				out.println("<td><b>");
				out.println(contentInfo.binaryFlagName(i));
				out.println("</b></td>");
				if(pkg != null){
					out.println("<td>");
					out.println(pkg.binaryFlag(i));
					out.println("</td>");
				}
				out.println("</tr>");
			}
			out.println("</tbody>");
			out.println("</table>");
		}

		if(contentInfo.integerFlagNum() != 0){
			out.println("<div style=\"margin: 15px; color:#ffffff; background:#1d6d82;\">");
			out.println("<h4> Integer-Ranged(32bit) Value Flag </h4>");
			out.println("</div>");

			out.println("<table style=\"margin: 25px;\">");
			out.println("<tbody>");
			out.println("<tr style=\"color: #ffffff; background: #155161;\">");
			out.println("<th></th>");
			out.println("<th>");
			out.println("Field name");
			out.println("</th>");
			if(pkg != null){
				out.println("<th>");
				out.println("Latest indexed value");
				out.println("</th>");
			}
			out.println("</tr>");
			for(int i = 0; i < contentInfo.integerFlagNum(); i++){
				out.println("<tr style=\"background: " + (i % 2 == 0? "#cccccc": "#ffffff") + "\">");
				out.println("<td style=\"font-style: italic;\">");
				if(conf.uniqueType() == Constants.DELETE_TYPE_INTFLAG && conf.uniqueIndex() == i)
					out.println("Unique key");
				out.println("</td>");
				out.println("<td><b>");
				out.println(contentInfo.integerFlagName(i));
				out.println("</b></td>");
				if(pkg != null){
					out.println("<td>");
					out.println(pkg.intFlag(i));
					out.println("</td>");
				}
				out.println("</tr>");
			}
			out.println("</tbody>");
			out.println("</table>");
		}

		if(contentInfo.longFlagNum() != 0){
			out.println("<div style=\"margin: 15px; color:#ffffff; background:#1d6d82;\">");
			out.println("<h4> Long-Ranged(64bit) Value Flag </h4>");
			out.println("</div>");

			out.println("<table style=\"margin: 25px;\">");
			out.println("<tbody>");
			out.println("<tr style=\"color: #ffffff; background: #155161;\">");
			out.println("<th></th>");
			out.println("<th>");
			out.println("Field name");
			out.println("</th>");
			if(pkg != null){
				out.println("<th>");
				out.println("Latest indexed value");
				out.println("</th>");
			}
			out.println("</tr>");
			for(int i = 0; i < contentInfo.longFlagNum(); i++){
				out.println("<tr style=\"background: " + (i % 2 == 0? "#cccccc": "#ffffff") + "\">");
				out.println("<td style=\"font-style: italic;\">");
				if(conf.uniqueType() == Constants.DELETE_TYPE_LONGFLAG && conf.uniqueIndex() == i)
					out.println("Unique key");
				out.println("</td>");
				out.println("<td><b>");
				out.println(contentInfo.longFlagName(i));
				out.println("</b></td>");
				if(pkg != null){
					out.println("<td>");
					out.println(pkg.longFlag(i));
					out.println("</td>");
				}
				out.println("</tr>");
			}
			out.println("</tbody>");
			out.println("</table>");
		}

		if(contentInfo.floatFlagNum() != 0){
			out.println("<div style=\"margin: 15px; color:#ffffff; background:#1d6d82;\">");
			out.println("<h4> Floating Value Flag </h4>");
			out.println("</div>");

			out.println("<table style=\"margin: 25px;\">");
			out.println("<tbody>");
			out.println("<tr style=\"color: #ffffff; background: #155161;\">");
			out.println("<th>");
			out.println("Field name");
			out.println("</th>");
			if(pkg != null){
				out.println("<th>");
				out.println("Latest indexed value");
				out.println("</th>");
			}
			out.println("</tr>");
			for(int i = 0; i < contentInfo.floatFlagNum(); i++){
				out.println("<tr style=\"background: " + (i % 2 == 0? "#cccccc": "#ffffff") + "\">");
				out.println("<td><b>");
				out.println(contentInfo.floatFlagName(i));
				out.println("</b></td>");
				if(pkg != null){
					out.println("<td>");
					out.println(pkg.floatFlag(i));
					out.println("</td>");
				}
				out.println("</tr>");
			}
			out.println("</tbody>");
			out.println("</table>");
		}

		// ///////////////////////////////

		out.println("<div style=\"background:#268eab; color:#ffffff;\">");
		out.println("<h3> Memory </h3>");
		out.println("</div>");

		out.println("<table style=\"margin: 15px;\">");
		out.println("<tbody>");

		out.println("<tr style=\"background: #aaaaaa;\">");
		out.println("<th>");
		out.println("Cluster");
		out.println("</th>");
		out.println("<th>");
		out.println("Block ID");
		out.println("</th>");
		out.println("<th>");
		out.println("Name");
		out.println("</th>");
		out.println("<th>");
		out.println("Used/Capacity");
		out.println("</th>");
		out.println("<th>");
		out.println("Percent");
		out.println("</th>");
		out.println("</tr>");

		int count = 0;
		for(MemoryInfoMaterial block: meminfo){
			out.println("<tr style=\"background: " + (count++ % 2 == 1? "#ffffff": "#cccccc") + ";\">");
			out.println("<td>");
			out.println(block.clusterID());
			out.println("</td>");
			out.println("<td>");
			out.println(block.blockID());
			out.println("</td>");
			out.println("<td>");
			out.println(block.className());
			out.println("</td>");
			out.println("<td align=\"right\">");
			out.println(block.usedSize() + "/" + block.capacity());
			out.println("</td>");
			out.println("<td align=\"right\"><b>");
			out.println(String.format("%5.2f", block.usedPercent()) + "%");
			out.println("</b></td>");
			out.println("</tr>");
		}

		out.println("</tbody>");
		out.println("</table>");

		// ///////////////////////////////

		out.println("<div style=\"background:#268eab; color:#ffffff;\">");
		out.println("<h3> Node </h3>");
		out.println("</div>");

		SortedSet<Node> nodes = srv.getNode();

		out.println("<table style=\"margin: 15px;\">");
		out.println("<tbody>");

		out.println("<tr style=\"background: #aaaaaa;\">");
		out.println("<th>");
		out.println("IP address");
		out.println("</th>");
		out.println("<th>");
		out.println("Port");
		out.println("</th>");
		out.println("<th>");
		out.println("Hash");
		out.println("</th>");
		out.println("<th>");
		out.println("Live/Suspend");
		out.println("</th>");
		out.println("</tr>");

		count = 0;
		for(Node node: nodes){
			out.println("<tr style=\"background: " + (count++ % 2 == 1? "#ffffff": "#cccccc") + ";\">");
			out.println("<td>");
			out.println(node.getAddr());
			out.println("</td>");
			out.println("<td>");
			out.println(node.getPort());
			out.println("</td>");
			out.println("<td align=\"right\">");
			out.println(node.getAttributeHash(0x8000000000000000L));
			out.println("</td>");
			out.println("<td>");
			out.println(node.isSuspend()? "Suspend": "Live");
			out.println("</td>");
			out.println("</tr>");
		}

		out.println("</tbody>");
		out.println("</table>");

		out.println("</body>");
		out.println("</html>");
	}
}
